package org.hcyspartnoc.luoxin.utils;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.toolkit.Db;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import io.netty.channel.Channel;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import okhttp3.*;
import org.hcyspartnoc.luoxin.common.core.AjaxResult;
import org.hcyspartnoc.luoxin.common.core.configuration.ContrapsychConfiguration;
import org.hcyspartnoc.luoxin.common.core.configuration.ServiceConfiguration;
import org.hcyspartnoc.luoxin.common.enums.chat.ChatMessageStatusEnum;
import org.hcyspartnoc.luoxin.common.enums.chat.ChatMessageTypeEnum;
import org.hcyspartnoc.luoxin.common.enums.chat.ChatSenderTypeEnum;
import org.hcyspartnoc.luoxin.common.enums.service.ServiceCounselorStatusEnum;
import org.hcyspartnoc.luoxin.common.enums.user.UserContactTypeEnum;
import org.hcyspartnoc.luoxin.common.exception.asset.AssetVCounselorException;
import org.hcyspartnoc.luoxin.common.exception.chat.ChatException;
import org.hcyspartnoc.luoxin.common.exception.user.UserContactException;
import org.hcyspartnoc.luoxin.mapper.asset.AssetVirtualCounselorMapper;
import org.hcyspartnoc.luoxin.mapper.chat.ChatCounselingSessionMapper;
import org.hcyspartnoc.luoxin.mapper.chat.ChatSessionMapper;
import org.hcyspartnoc.luoxin.mapper.chat.ChatSessionUserMapper;
import org.hcyspartnoc.luoxin.mapper.system.SysUserMapper;
import org.hcyspartnoc.luoxin.mapper.user.UserContactMapper;
import org.hcyspartnoc.luoxin.pojo.dto.chat.ChatMessageDto;
import org.hcyspartnoc.luoxin.pojo.po.asset.AssetVirtualCounselorPo;
import org.hcyspartnoc.luoxin.pojo.po.chat.ChatCounselingSessionPo;
import org.hcyspartnoc.luoxin.pojo.po.chat.ChatMessagePo;
import org.hcyspartnoc.luoxin.pojo.po.chat.ChatSessionPo;
import org.hcyspartnoc.luoxin.pojo.po.chat.ChatSessionUserPo;
import org.hcyspartnoc.luoxin.pojo.po.service.ServiceCounselorOrderPo;
import org.hcyspartnoc.luoxin.pojo.po.system.SysUserPo;
import org.hcyspartnoc.luoxin.pojo.po.user.UserContactPo;
import org.hcyspartnoc.luoxin.pojo.vo.chat.ChatCommonVo;
import org.hcyspartnoc.luoxin.pojo.vo.chat.ChatInitVo;
import org.hcyspartnoc.luoxin.pojo.vo.chat.ChatSessionUserVo;
import org.hcyspartnoc.luoxin.utils.redis.RedisComponent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.*;

@Component
public class LuoxinUtils {
    private static final Logger logger = LoggerFactory.getLogger(LuoxinUtils.class);
    private static final ArrayList<String> SPLIT_SENTENCE_PUNCTUATION;
    private static final Integer MIN_SENTENCE_LENGTH = 15;
    public static MediaType JSON_FORMAT = MediaType.parse("application/json; charset=utf-8");
    public static final String LUOXIN_SYSTEM_ROLE = "system";
    public static final String LUOXIN_AI_ROLE = "assistant";
    public static final String LUOXIN_USER_ROLE = "user";

    static {
        SPLIT_SENTENCE_PUNCTUATION = new ArrayList<>();
        SPLIT_SENTENCE_PUNCTUATION.add(",");
        SPLIT_SENTENCE_PUNCTUATION.add(",\n");
        SPLIT_SENTENCE_PUNCTUATION.add("?");
        SPLIT_SENTENCE_PUNCTUATION.add("?\n");
        SPLIT_SENTENCE_PUNCTUATION.add("!");
        SPLIT_SENTENCE_PUNCTUATION.add("!\n");
        SPLIT_SENTENCE_PUNCTUATION.add("。");
        SPLIT_SENTENCE_PUNCTUATION.add("。\n");
        SPLIT_SENTENCE_PUNCTUATION.add("！");
        SPLIT_SENTENCE_PUNCTUATION.add("！\n");
        SPLIT_SENTENCE_PUNCTUATION.add("？");
        SPLIT_SENTENCE_PUNCTUATION.add("？\n");
        SPLIT_SENTENCE_PUNCTUATION.add("，");
        SPLIT_SENTENCE_PUNCTUATION.add("，\n");
    }

    @Resource
    private RedisComponent redisComponent;
    @Resource
    private UserContactMapper userContactMapper;
    @Resource
    private ChatSessionMapper chatSessionMapper;
    @Resource
    private ChatSessionUserMapper chatSessionUserMapper;
    @Resource
    private AssetVirtualCounselorMapper assetVirtualCounselorMapper;
    @Resource
    private SysUserMapper sysUserMapper;
    @Resource
    private ContrapsychConfiguration contrapsychConfiguration;
    @Resource
    private AliyunOssUtils aliyunOssUtils;
    @Resource
    private WavCompose wavCompose;
    @Resource
    private ChatCounselingSessionMapper chatCounselingSessionMapper;
    @Resource
    private ServiceConfiguration serviceConfiguration;
    @Autowired
    private ChannelContextUtils channelContextUtils;

    // TODO ->后续需要将部分查库优化为redis
    public void askQuestion(ChatMessageDto chatMessageDto, String uid, Channel channel, ChatMessageTypeEnum chatMessageTypeEnum) {
        String chatAnswer = "";
        String totalAudio = "";
        String chatReqBody = "";
        ChatSessionPo chatSessionPo = null;
        boolean isTimesEnough = true;
        ArrayList<String> allAudioFiles = new ArrayList<>();
        try {
            // 检查是否发送人和联系人是否存在关系
            UserContactPo userContactPo = userContactMapper.selectOne(new LambdaQueryWrapper<>(UserContactPo.class)
                    .eq(UserContactPo::getUserId, uid)
                    .eq(UserContactPo::getId, chatMessageDto.getContactId())
                    .eq(UserContactPo::getContactType, UserContactTypeEnum.V_COUNSELOR.getCode()));
            // 如果该用户没有此联系人
            if (Objects.isNull(userContactPo)) {
                sendErrorBody(UserContactException.CONTACT_NOT_EXISTS, channel);
                return;
            }
            // 查询虚拟人信息
            AssetVirtualCounselorPo assetVirtualCounselorPo = assetVirtualCounselorMapper.selectById(userContactPo.getContactId());
            // 如果虚拟人不存在抛出异常
            if (Objects.isNull(assetVirtualCounselorPo)) {
                sendErrorBody(AssetVCounselorException.VIRTUAL_COUNSELOR_NOT_EXITS, channel);
                return;
            }
            // 检查是否已经存在会话
            ChatSessionUserPo savedSessionUserPo = chatSessionUserMapper.selectOne(new LambdaQueryWrapper<>(ChatSessionUserPo.class)
                    .eq(ChatSessionUserPo::getContactId, userContactPo.getId())
                    .eq(ChatSessionUserPo::getUserId, uid));
            if (Objects.isNull(savedSessionUserPo)) {
                // 生成sessionId，规则，双方身份加双方id排序后生成md5
                String sessionId = generateSessionId('U' + uid, 'V' + assetVirtualCounselorPo.getId().toString());
                chatSessionPo = chatSessionMapper.selectById(sessionId);
                // 是否存在会话,不存在则创建一个会话
                if (Objects.isNull(chatSessionPo)) {
                    // 创建一个会话
                    chatSessionPo = new ChatSessionPo();
                    chatSessionPo.setId(sessionId);
                    chatSessionPo.setFreeChatTimes(contrapsychConfiguration.getChat().getDailyFree());
                    chatSessionMapper.insert(chatSessionPo);
                }
                // 创建用户会话对应关系
                savedSessionUserPo = new ChatSessionUserPo();
                savedSessionUserPo.setSessionId(chatSessionPo.getId())
                        .setContactId(userContactPo.getId())
                        .setUserId(Integer.parseInt(uid))
                        .setContactName(assetVirtualCounselorPo.getName())
                        .setContactAvatar(assetVirtualCounselorPo.getAvatar());
                chatSessionUserMapper.insert(savedSessionUserPo);
            } else {
                chatSessionPo = chatSessionMapper.selectById(savedSessionUserPo.getSessionId());
            }

            // 如果是空抛出异常
            if (Objects.isNull(chatMessageDto.getMessageContent()) || chatMessageDto.getMessageContent().isEmpty()) {
                sendErrorBody(ChatException.TEXT_CONTENT_ERROR, channel);
                return;
            }

            // 判断是否为有进行中的订单会话，如果有则将消息存入订单会话，没有则存入主会话
            MPJLambdaWrapper<ChatCounselingSessionPo> eqOfCCSP = new MPJLambdaWrapper<ChatCounselingSessionPo>()
                    .leftJoin(ServiceCounselorOrderPo.class, ServiceCounselorOrderPo::getCounselorId, ChatCounselingSessionPo::getCounselorId)
                    .eq(ChatCounselingSessionPo::getStatus, true)
                    .eq(ChatCounselingSessionPo::getMasterSessionId, chatSessionPo.getId())
                    .eq(ServiceCounselorOrderPo::getStatus, ServiceCounselorStatusEnum.IN_PROGRESS.getCode());
            ChatCounselingSessionPo chatCounselingSessionPo = chatCounselingSessionMapper.selectOne(eqOfCCSP);
            // 获取用户 TODO—>后续通过redis优化
            SysUserPo currentUserPo = sysUserMapper.selectById(Integer.parseInt(uid));

            // 将用户消息记录到主会话数据表里
            ChatMessagePo userMessagePo = new ChatMessagePo();
            userMessagePo.setMessageContent(chatMessageDto.getMessageContent())
                    .setMessageType(ChatMessageTypeEnum.CHAT_V_COUNSELOR.getCode())
                    .setSenderId(currentUserPo.getId())
                    .setSenderType(ChatSenderTypeEnum.USER.getCode())
                    .setSenderNickname(currentUserPo.getNickname())
                    .setContactId(userContactPo.getId())
                    .setStatus(ChatMessageStatusEnum.HAS_SEND.getCode());
            if (Objects.isNull(chatCounselingSessionPo)) {
                // 操作主会话
                // 判断是否有足够的免费消息
                if (chatSessionPo.getFreeChatTimes() == 0) {
                    isTimesEnough = false;
                    return;
                }
                // 将消息会话id设置会主会话id
                userMessagePo.setSessionId(chatSessionPo.getId());

            } else {
                // 操作订单会话
                // 将消息会话id设置为订单会话id->如何区分主会话和订单会话？通过长度区分，主会话id为32位数，订单会话id小于32
                userMessagePo.setSessionId(chatCounselingSessionPo.getId().toString());
            }
            Db.save(userMessagePo);


            /*--获取咨询师响应--*/
            // 构造请求体
            String chatMemory;
            if (Objects.isNull(chatCounselingSessionPo)) {
                // 操作主会话
                // 获取主会话的记忆体
                chatMemory = redisComponent.getChatVCMemory(chatSessionPo.getId());
            } else {
                // 操作订单会话
                // 获取订单会话的记忆体->订单会话记忆体会在订单结束轮询中清除
                chatMemory = redisComponent.getChatOrderVCMemory(chatCounselingSessionPo.getId().toString());
            }

            MultimediaUtils.ChatReqBody baseResBody;
            if (Objects.isNull(chatMemory)) {
                // 构造一个新的记忆体
                baseResBody = MultimediaUtils.ChatReqBody.getBaseResBody();
                ArrayList<MultimediaUtils.ChatReqBody.Message> messages = new ArrayList<>();
                messages.add(new MultimediaUtils.ChatReqBody.Message(LUOXIN_SYSTEM_ROLE, assetVirtualCounselorPo.getPrompt() + serviceConfiguration.getChat().getPublicPrompt()));
                messages.add(new MultimediaUtils.ChatReqBody.Message(LUOXIN_USER_ROLE, chatMessageDto.getMessageContent()));
                baseResBody.setMessages(messages);
            } else {
                baseResBody = JSON.parseObject(chatMemory, MultimediaUtils.ChatReqBody.class);
                baseResBody.getMessages().add(new MultimediaUtils.ChatReqBody.Message(LUOXIN_USER_ROLE, chatMessageDto.getMessageContent()));
            }
            chatReqBody = JSON.toJSONString(baseResBody);
            RequestBody body = RequestBody.create(chatReqBody, JSON_FORMAT);
            Request request = new Request.Builder()
                    .url(contrapsychConfiguration.getChat().getUrl())
                    .post(body)
                    .build();
            OkHttpClient client = new OkHttpClient();
            int maxRetries = contrapsychConfiguration.getChat().getMaxRetries();

            // 获取回答，最多尝试次数在配置文件中配置
            while (maxRetries-- > 0) {
                try (Response response = client.newCall(request).execute()) {
                    if (!response.isSuccessful()) System.out.println("successError");
                    try (ResponseBody responseBody = response.body()) {
                        if (responseBody != null) {
                            byte[] buffer = new byte[1024];
                            int bytesRead;
                            String sentence = "";
                            String line;
                            StringBuilder totalSentence = new StringBuilder();
                            while ((bytesRead = responseBody.byteStream().read(buffer)) != -1) {
                                line = new String(buffer, 0, bytesRead, StandardCharsets.UTF_8);
                                // 过滤空字符
                                line = line.replaceAll("[\\n\\r\\t\\v\\f]", "");
                                sentence += line;
                                // 进行语句判断
                                if (SPLIT_SENTENCE_PUNCTUATION.contains(line) && sentence.length() > MIN_SENTENCE_LENGTH) {
                                    sentence = sentence.replace("*", "");
                                    sentence = sentence.replace(assetVirtualCounselorPo.getName() + " :", "");
                                    totalSentence.append(sentence);
                                    sendAudioSentence(allAudioFiles, sentence, assetVirtualCounselorPo.getAlias(), chatMessageTypeEnum, chatSessionPo.getId(), channel);
                                    //清空语句
                                    sentence = "";
                                }
                            }
                            if (sentence.length() > 1) {
                                boolean flag = false;
                                for (int i = 0; i < sentence.length(); i++)
                                    if (SPLIT_SENTENCE_PUNCTUATION.contains(Character.valueOf(sentence.charAt(i)).toString())) {
                                        flag = true;
                                        break;
                                    }
                                if (flag) {
                                    sentence = sentence.replace("*", "");
                                    sentence = sentence.replace(assetVirtualCounselorPo.getName() + " :", "");
                                    totalSentence.append(sentence);
                                    sendAudioSentence(allAudioFiles, sentence, assetVirtualCounselorPo.getAlias(), chatMessageTypeEnum, chatSessionPo.getId(), channel);
                                }
                            }
                            chatAnswer = totalSentence.toString();
                            // 合成总音频
                            totalAudio = wavCompose.addWavToBase64(allAudioFiles.toArray(new String[0]));
                        }
                    }
                    break;
                } catch (Exception e) {
                    logger.error(e.getMessage());
                }
            }

            // 将机器人消息记录到会话
            ChatMessagePo chatMessagePo = new ChatMessagePo();
            chatMessagePo.setMessageContent(chatAnswer)
                    .setMessageType(ChatMessageTypeEnum.CHAT_V_COUNSELOR.getCode())
                    .setContactId(userContactPo.getUserId())// 机器人设置的联系人id为用户的id
                    .setSenderId(assetVirtualCounselorPo.getId())
                    .setStatus(ChatMessageStatusEnum.HAS_SEND.getCode())
                    .setSenderNickname(assetVirtualCounselorPo.getName())
                    .setSenderType(ChatSenderTypeEnum.V_COUNSELOR.getCode());
            if (Objects.isNull(chatCounselingSessionPo)) {
                // 操作主会话
                // 将消息会话id设置会主会话id
                chatMessagePo.setSessionId(chatSessionPo.getId());
            } else {
                // 操作订单会话
                // 将消息会话id设置为订单会话id->如何区分主会话和订单会话？通过长度区分，主会话id为32位数，订单会话id小于32
                chatMessagePo.setSessionId(chatCounselingSessionPo.getId().toString());
            }
            Db.save(chatMessagePo);

            // 将会话消息记录到记忆体中
            baseResBody.getMessages().add(new MultimediaUtils.ChatReqBody.Message(LUOXIN_AI_ROLE, chatAnswer));
            if (Objects.isNull(chatCounselingSessionPo)) {
                // 操作主会话
                // 将免费次数-1
                chatSessionPo.setLastSendTime(LocalDateTime.now());
                if (chatSessionPo.getFreeChatTimes() != -1) {
                    chatSessionPo.setFreeChatTimes(chatSessionPo.getFreeChatTimes() - 1);
                    if (chatSessionPo.getFreeChatTimes() == 0)
                        isTimesEnough = false;
                }
                // 将请求记忆缓存
                redisComponent.setChatVCMemory(chatSessionPo.getId(), JSON.toJSONString(baseResBody));
            } else {
                // 记录记忆缓存
                redisComponent.setChatOrderVcMemory(chatCounselingSessionPo.getId().toString(), JSON.toJSONString(baseResBody));
            }
            //更新会话最后一条消息
            chatSessionPo.setMessage(chatAnswer);
            Db.saveOrUpdate(chatSessionPo);


        } catch (Exception e) {
            logger.error("askQuestionError:{}", e.getMessage());
        } finally {
            logger.info("\n用户：{} \n请求参数：{}\nAI回答：{}\nchat接口参数{}",
                    uid, JSON.toJSONString(chatMessageDto), chatAnswer, chatReqBody);
            // 返回结束标志
            ChatWithVCRes chatRes = new ChatWithVCRes(chatAnswer, totalAudio, true, isTimesEnough);
            ChatCommonVo chatCommonVo = new ChatCommonVo();
            chatCommonVo.setMessageType(chatMessageTypeEnum)
                    .setMessageContent(chatRes);
            if (Objects.nonNull(chatSessionPo)) {
                chatCommonVo.setSessionId(chatSessionPo.getId());
            }
            SendSuccessBody(chatCommonVo, channel);
        }
    }

    public void audioChatWithVc(ChatMessageDto chatMessageDto, String uid, Channel channel) {
        // 将文本转为base64
        String question = MultimediaUtils.base64ToText(chatMessageDto.getMessageContent());
        // 转述给askQuestion
        chatMessageDto.setMessageContent(question);
        askQuestion(chatMessageDto, uid, channel, ChatMessageTypeEnum.AUDIO_CHAT_VC);
    }

    // 初始化连接
    public void initConnection(String uid, Channel channel) {
        // 预热chat和tts模型
        new Thread(() -> {
            // chat
            MultimediaUtils.ChatReqBody baseResBody = MultimediaUtils.ChatReqBody.getBaseResBody();
            ArrayList<MultimediaUtils.ChatReqBody.Message> messages = new ArrayList<>();
            messages.add(new MultimediaUtils.ChatReqBody.Message(LUOXIN_SYSTEM_ROLE, "你是一个机器人"));
            messages.add(new MultimediaUtils.ChatReqBody.Message(LUOXIN_USER_ROLE, "输出'你好'"));
            baseResBody.setMessages(messages);
            String chatAnswer = MultimediaUtils.getChatAnswer(baseResBody);
            // tts
            UUID uuid = UUID.randomUUID();
            String filePath = contrapsychConfiguration.getTempFilesDir() + uuid + ".wav";
            String audio = MultimediaUtils.textToWavBase64(chatAnswer, filePath, "luoxin");
            if (Objects.isNull(audio))
                audio = "";
            System.out.println("预热：" + chatAnswer + " 音频：" + audio.length());
        }).start();
        // 记录初始化消息
        // 将用户消息记录到数据库
        ChatMessagePo chatMessagePo = new ChatMessagePo();
        chatMessagePo.setMessageType(ChatMessageTypeEnum.INIT.getCode())
                .setMessageContent(ChatMessageTypeEnum.INIT.getMessage())
                .setStatus(ChatMessageStatusEnum.HAS_SEND.getCode())
                .setSenderId(Integer.parseInt(uid))
                .setSenderType(ChatSenderTypeEnum.USER.getCode());
        Db.save(chatMessagePo);
        // 查询该用户所拥有的所有会话
        MPJLambdaWrapper<ChatSessionUserPo> eq = new MPJLambdaWrapper<ChatSessionUserPo>()
                .leftJoin(ChatSessionPo.class, ChatSessionPo::getId, ChatSessionUserPo::getSessionId)
                .selectAll(ChatSessionUserPo.class)
                .selectAs(ChatSessionPo::getMessage, ChatSessionUserPo::getMessage)
                .selectAs(ChatSessionPo::getLastSendTime, ChatSessionUserPo::getLastSendTime)
                .eq(ChatSessionUserPo::getUserId, Integer.parseInt(uid));
        List<ChatSessionUserPo> chatSessionUserPos = chatSessionUserMapper.selectJoinList(ChatSessionUserPo.class, eq);
        ArrayList<ChatSessionUserVo> chatSessionUserVos = new ArrayList<>();
        for (ChatSessionUserPo chatSessionUserPo : chatSessionUserPos) {
            ChatSessionUserVo chatSessionUserVo = BeanUtil.copyProperties(chatSessionUserPo, ChatSessionUserVo.class);
            chatSessionUserVo.setContactAvatar(aliyunOssUtils.generateUrl(chatSessionUserVo.getContactAvatar()));
            chatSessionUserVos.add(chatSessionUserVo);
        }
        ChatInitVo chatInitVo = new ChatInitVo();
        chatInitVo.setChatSessionUserVos(chatSessionUserVos);
        // 构建响应体
        ChatCommonVo chatCommonVo = new ChatCommonVo();
        chatCommonVo.setMessageType(ChatMessageTypeEnum.INIT)
                .setMessageContent(chatInitVo);
        SendSuccessBody(chatCommonVo, channel);
    }

    @Data
    @Accessors(chain = true)
    @NoArgsConstructor
    @AllArgsConstructor
    public static class ChatWithVCRes {
        private String sentence;
        private String base64Audio;
        private Boolean finishStatus;
        private Boolean isTimesEnough;

        public ChatWithVCRes(String sentence, String base64Audio, Boolean finishStatus) {
            this.sentence = sentence;
            this.base64Audio = base64Audio;
            this.finishStatus = finishStatus;
            this.isTimesEnough = true;
        }
    }

    public static void SendSuccessBody(ChatCommonVo chatCommonVo, Channel channel) {
        // 构建响应体
        channel.writeAndFlush(new TextWebSocketFrame(JSON.toJSONString(AjaxResult.success(chatCommonVo))));
        channel.flush();
    }

    public static void sendErrorBody(String errorMsg, Channel channel) {
        channel.writeAndFlush(new TextWebSocketFrame(JSON.toJSONString(AjaxResult.errorMsg_400(errorMsg))));
        channel.flush();
    }

    public static String generateSessionId(String p1, String p2) {
        TreeSet<String> strings = new TreeSet<>();
        strings.add(p1);
        strings.add(p2);
        String resultStr = "";
        for (String str : strings) {
            resultStr += str;
        }
        return StringUtils.encodeByMd5(resultStr);
    }

    private void sendAudioSentence(ArrayList<String> allAudioFiles, String sentence, String alias, ChatMessageTypeEnum chatMessageTypeEnum, String sessionId, Channel channel) {
        // 生成音频
        UUID uuid = UUID.randomUUID();
        String filePath = contrapsychConfiguration.getTempFilesDir() + uuid + ".wav";
        String base64Audio = null;
        int maxRetriesNum = contrapsychConfiguration.getTts().getMaxRetries();
        while (Objects.isNull(base64Audio) || base64Audio.isEmpty()) {
            base64Audio = MultimediaUtils.textToWavBase64(sentence, filePath, alias);
            if (--maxRetriesNum == 0)
                break;
        }
        allAudioFiles.add(filePath);
        // 返回响应
        LuoxinUtils.ChatWithVCRes chatRes = new LuoxinUtils.ChatWithVCRes(sentence, base64Audio, false);
        ChatCommonVo chatCommonVo = new ChatCommonVo();
        chatCommonVo.setMessageType(chatMessageTypeEnum)
                .setSessionId(sessionId)
                .setMessageContent(chatRes);
        LuoxinUtils.SendSuccessBody(chatCommonVo, channel);
    }
}
